#pragma once

template<typename DATA_TYPE>
class LinkedList{
private:
	struct Node{
		DATA_TYPE m_data;
		Node *m_next;
		Node *m_prev;
		Node()
			:m_next(0), m_prev(0){};
	};

	Node *m_root;

	void RenewRoot();

	void ClearList(DATA_TYPE a_DATA_TYPE);
public:
	LinkedList();
	~LinkedList();

	int Get_Size();
	void Insert_ToEnd(DATA_TYPE a_data);
	void Remove_FromEnd();
	void Remove_FromIndex(unsigned int a_index);
	DATA_TYPE Get_Data(unsigned int a_index);
	void Clear();
};

/***************************************************************************************************/

template<typename DATA_TYPE>
class LinkedList<DATA_TYPE *>{
private:
	struct Node{
		DATA_TYPE *m_data;
		Node *m_next;
		Node *m_prev;
		Node()
			:m_next(0), m_prev(0){};
	};

	Node *m_root;

	void RenewRoot();
	
	void ClearList(DATA_TYPE *&a_DATA_TYPE);
public:
	LinkedList();
	~LinkedList();

	int Get_Size();
	void Insert_ToEnd(DATA_TYPE *a_data);
	void Remove_FromEnd();
	void Remove_FromEndPtr(unsigned int a_index);
	void Remove_FromIndex(unsigned int a_index);
	void Remove_FromIndexPtr(unsigned int a_index);
	DATA_TYPE *Get_Data(unsigned int a_index);
	void Clear();
	void ClearPtr();
};